home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 2002 Tom Parker (tom@carrott.org),
- Matthias Münch (matthias@amigaworld.de)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- In addition, as a special exception, Tom Parker and Matthias Münch give
- permission to link the code of this program with a TCP stack of your
- choice, any official MUI libraries or classes and any custom MUI classes
- that should be necessary for the operation of this program. This
- exception also gives you permission to distribute linked combinations
- including this software with any of the before-mentioned libraries and
- classes. You must obey the GNU General Public License in all respects for
- all of the code used other than that provided by the before-mentioned
- libraries and classes. As part of this exception you are obliged to
- follow the license terms of the before-mentioned libraries, this license
- does not compel you to follow those terms, but if you do not then you may
- not link with those libraries. If you modify this file, you may extend
- this exception to your version of the file, but you are not obligated to
- do so. If you do not wish to do so, delete this exception statement from
- your version.
- */
- /*
- ** group chat window
- */
-
- #include "common.h"
- #include "edit.h"
-
- #include <MUI/NListview_mcc.h>
-
- static list *gc_list = NULL;
-
- static ULONG gchat_new(struct IClass *cl, Object *obj, struct opSet *msg);
- static MUI_LIST_DISP_DECL(userlist_disp, struct gc_user *u);
- static MUI_LIST_DEST_DECL(userlist_dest, struct gc_user *u);
- static MUI_LIST_COMP_DECL(userlist_comp, struct gc_user *u1, struct gc_user *u2);
- static void gchat_send(Object *obj, struct gchatdata *data);
- static void gchat_presence(struct gchatdata *data, ikspak *pak);
- static void gchat_message(struct gchatdata *data, ikspak *pak);
-
- static void gchat_people(struct gchatdata *data, int diff)
- {
- if(!data->gcw) return;
-
- data->gcw->people += diff;
- if(data->gcw->people == 0)
- set(data->numtxt, MUIA_Text_Contents, (ULONG) "-empty-");
- else
- set(data->numtxt, MUIA_Text_Contents, (ULONG) my_printf("%ld people", data->gcw->people));
- }
-
- static void gchat_nick(struct gchatdata *data, char *nick)
- {
- if(!nick || !*nick) return;
-
- if(data->nick) free(data->nick);
- data->nick = strdup(nick);
-
- DoMethod(data->rect, MUIM_Group_InitChange);
- set(data->nicktxt, MUIA_Text_Contents, (ULONG) data->nick);
- DoMethod(data->rect, MUIM_Group_ExitChange);
- }
-
-
- MUI_DISPATCH(gchat_dispatch)
- {
- switch(msg->MethodID)
- {
- case OM_NEW:
- return gchat_new(cl, obj, (APTR)msg);
-
- case GCHAT_CLOSE:
- {
- struct gchatdata *data = INST_DATA(cl,obj);
- list_remove(&gc_list, data->gcw);
- if(data->gcw->id)
- {
- iks *x;
- x = iks_make_pres(IKS_TYPE_UNAVAILABLE, 0, iks_id_print(data->gcw->id), NULL);
- iks_send(net.parser, x);
- iks_delete(x);
- }
- free(data->gcw);
- DoMethod(gui.app, MUIM_Application_PushMethod, gui.list, 2, ROSTER_CLOSEME, obj);
- return 0;
- }
-
- case GCHAT_TOPIC:
- {
- struct gchatdata *data = INST_DATA(cl,obj);
- iks *x;
- char *tmp;
-
- tmp = mui_sget(data->topicstr);
- if(tmp)
- {
- x = iks_make_msg(IKS_TYPE_GROUPCHAT, iks_id_print(data->gcw->id), NULL, NULL);
- iks_insert_cdata(iks_insert(x, "subject"), convert_utf8(tmp), -1);
- iks_send(net.parser, x);
- iks_delete(x);
- }
- set(obj, MUIA_Window_ActiveObject, (ULONG) data->msgstr);
- return 0;
- }
-
- case GCHAT_SEND:
- gchat_send(obj, INST_DATA(cl,obj));
- return 0;
-
- case GCHAT_PACKET:
- {
- struct gchatdata *data = INST_DATA(cl,obj);
- ikspak *pak = (ikspak *)MARG1;
-
- if(pak->type == IKS_PAK_PRESENCE)
- gchat_presence(data, pak);
- else
- gchat_message(data, pak);
-
- return 0;
- }
-
- }
- return DoSuperMethodA(cl, obj, msg);
- }
-
-
- static ULONG gchat_new(struct IClass *cl, Object *obj, struct opSet *msg)
- {
- static struct Hook dispHook = { {0,0}, &userlist_disp, NULL, NULL };
- static struct Hook destHook = { {0,0}, &userlist_dest, NULL, NULL };
- static struct Hook compHook = { {0,0}, &userlist_comp, NULL, NULL };
- struct gchatdata *data;
- struct gc_win *gcw;
- Object *chantxt, *topicstr, *msglist, *userlist, *numtxt, *rect, *nicktxt, *msgstr;
-
- obj = (Object *)DoSuperNew(cl, obj,
- MUIA_Window_Title, "Jabber Conference",
- MUIA_Window_ID, mui_id(gui.app, "GCH"),
- MUIA_HelpNode, "window-conference",
- WindowContents, VGroup,
- Child, (ULONG) chantxt = TextObject,
- MUIA_Text_PreParse, "\33c",
- End,
- Child, HGroup,
- Child, Label2(MSG_GCHAT_TOPIC),
- Child, (ULONG) topicstr = TextinputObject,
- StringFrame,
- MUIA_String_MaxLen, 256,
- MUIA_CycleChain, 1,
- End,
- End,
- Child, HGroup,
- Child, (ULONG) msglist = NewObject(gui.chatarea_mcc->mcc_Class, NULL,
- MUIA_HorizWeight, 75,
- TAG_DONE),
- Child, BalanceObject, End,
- Child, VGroup,
- MUIA_HorizWeight, 25,
- Child, (ULONG) numtxt = TextObject,
- MUIA_Text_PreParse, "\33c",
- End,
- Child, NListviewObject,
- MUIA_NListview_NList, (ULONG) userlist = NListObject,
- InputListFrame,
- MUIA_NList_DisplayHook, &dispHook,
- MUIA_NList_DestructHook, &destHook,
- MUIA_NList_CompareHook, &compHook,
- MUIA_NList_DefaultObjectOnClick, FALSE,
- MUIA_NList_Format, "",
- MUIA_CycleChain, 1,
- End,
- End,
- End,
- End,
- Child, (ULONG) rect = HGroup,
- Child, (ULONG) nicktxt = TextObject,
- MUIA_HorizWeight, 0,
- End,
- Child, (ULONG) msgstr = NewObject(gui.edit_mcc->mcc_Class, NULL,
- EDIT_TYPE, EDIT_TYPE_CHAT,
- MUIA_CycleChain, 1,
- TAG_DONE),
- End,
- End,
- TAG_MORE, msg->ops_AttrList);
-
- if(!obj) return(NULL);
-
- set(obj, MUIA_Window_DefaultObject, (ULONG) msgstr);
- set(obj, MUIA_Window_ActiveObject, (ULONG) msgstr);
-
- gcw = malloc(sizeof(struct gc_win));
- memset(gcw, 0, sizeof(struct gc_win));
- gcw->win = obj;
- list_append(&gc_list, gcw);
-
- data = INST_DATA(cl,obj);
- data->chantxt = chantxt;
- data->topicstr = topicstr;
- data->msglist = msglist;
- data->userlist = userlist;
- data->numtxt = numtxt;
- data->rect = rect;
- data->nicktxt = nicktxt;
- data->msgstr = msgstr;
- data->gcw = gcw;
- data->nick = NULL;
- gcw->data = data;
-
- DoMethod(topicstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, obj, 1, GCHAT_TOPIC);
- DoMethod(msgstr, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, obj, 1, GCHAT_SEND);
- DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, obj, 1, GCHAT_CLOSE);
-
- gchat_people(data, 0);
-
- if(net.id)
- gchat_nick(data, net.id->user);
- else
- gchat_nick(data, "jwocky");
-
- return((ULONG)obj);
- }
-
-
- MUI_LIST_DISP_STATIC(userlist_disp, struct gc_user *u)
- {
- *array = u->nick;
- return 0;
- }
-
-
- MUI_LIST_DEST_STATIC(userlist_dest, struct gc_user *u)
- {
- gchat_people(u->gcw->data, -1);
-
- list_remove(&u->gcw->users, u);
- if(u->nick) free(u->nick);
- free(u);
-
- return 0;
- }
-
-
- MUI_LIST_COMP_STATIC(userlist_comp, struct gc_user *u1, struct gc_user *u2)
- {
- return iks_strcmp(u1->nick, u2->nick);
- }
-
-
- static void gchat_send(Object *obj, struct gchatdata *data)
- {
- char *tmp;
- iks *x;
-
- tmp = mui_sget(data->msgstr);
- if(!tmp) return;
-
- if(tmp[0] == '/')
- {
- if(strnicmp("join ", tmp+1, 5) == 0)
- {
- if(data->gcw->id)
- {
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Already joined.");
- goto out;
- }
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Joining...");
- data->gcw->id = iks_id_new(NULL, tmp+6);
- if(!data->gcw->id->resource) data->gcw->id->resource = data->nick;
- /* data->gcw->nick = strdup(data->gcw->id->resource);
- */ x = iks_make_pres(0, 0, iks_id_print(data->gcw->id), NULL);
- iks_send(net.parser, x);
- iks_delete(x);
- data->gcw->id->resource = NULL;
- data->gcw->id->full = NULL; /* FIX ME */
- set(data->chantxt, MUIA_Text_Contents, (ULONG) iks_id_print(data->gcw->id));
- }
- else if(strnicmp("part", tmp+1, 4) == 0)
- {
- if(!data->gcw->id) goto out;
- x = iks_make_pres(IKS_TYPE_UNAVAILABLE, 0, iks_id_print(data->gcw->id), NULL);
- iks_send(net.parser, x);
- iks_delete(x);
- data->gcw->id = NULL;
- set(data->chantxt, MUIA_Text_Contents, (ULONG) "");
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Channel left.");
- DoMethod(data->userlist, MUIM_NList_Clear);
- }
- else if(strnicmp("me ", tmp+1, 3) == 0)
- {
- if(!data->gcw->id)
- {
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Not joined.");
- goto out;
- }
- x = iks_make_msg(IKS_TYPE_GROUPCHAT, iks_id_print(data->gcw->id), convert_utf8(tmp), NULL);
- iks_send(net.parser, x);
- iks_delete(x);
- }
- else
- {
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Unknown command.");
- }
- }
- else
- {
- if(!data->gcw->id)
- {
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Not joined.");
- goto out;
- }
- x = iks_make_msg(IKS_TYPE_GROUPCHAT, iks_id_print(data->gcw->id), convert_utf8(tmp), NULL);
- iks_send(net.parser, x);
- iks_delete(x);
- }
-
-
- out:
- set(data->msgstr, MUIA_String_Contents, NULL);
- }
-
-
- static struct gc_user *gchat_finduser(struct gc_win *gcw, char *nick)
- {
- struct gc_user *u;
-
- if(!gcw->users) return(NULL);
- u = list_first(&gcw->users);
- while(u)
- {
- if(iks_strcmp(nick, u->nick) == 0) return(u);
- u = list_next(u);
- }
- return NULL;
- }
-
-
- static void gchat_presence(struct gchatdata *data, ikspak *pak)
- {
- struct gc_user *u;
-
- u = gchat_finduser(data->gcw, pak->from->resource);
- if(u)
- {
- long pos = MUIV_NList_GetPos_Start;
- if(pak->show != IKS_SHOW_UNAVAILABLE) return;
- DoMethod(data->userlist, MUIM_NList_GetPos, u->nick, &pos);
- if(data->gcw->state > 0) DoMethod(data->msglist, CHATAREA_ADD, 2, "<--", my_printf("%s has left.", u->nick));
- if(pos != MUIV_NList_GetPos_End) DoMethod(data->userlist, MUIM_NList_Remove, pos);
- }
- else
- {
- if(pak->show == IKS_SHOW_UNAVAILABLE) return;
- u = malloc(sizeof(struct gc_user));
- if(!u) return;
- u->nick = iks_strdup(pak->from->resource);
- u->gcw = data->gcw;
- list_append(&data->gcw->users, u);
- DoMethod(data->userlist, MUIM_NList_InsertSingle, u, MUIV_NList_Insert_Sorted);
- gchat_people(data, 1);
- if(data->gcw->state > 0) DoMethod(data->msglist, CHATAREA_ADD, 2, "-->", my_printf("%s has joined.", u->nick));
- if(data->gcw->state == 0 && iks_strcmp(data->nick, pak->from->resource) == 0)
- {
- DoMethod(data->msglist, CHATAREA_ADD, 2, "***", "Joined.");
- data->gcw->state = 1;
- }
- }
-
- return;
- }
-
-
- static void gchat_message(struct gchatdata *data, ikspak *pak)
- {
- char *body, *topic;
-
- body = iks_find_cdata(pak->x, "body");
- topic = iks_find_cdata(pak->x, "subject");
-
- if(topic)
- set(data->topicstr, MUIA_String_Contents, (ULONG) convert_locale(topic));
-
- if(pak->from->resource)
- {
- if(strnicmp("/me ", body, 4) == 0)
- DoMethod(data->msglist, CHATAREA_ADD, 0, "\33r\33b*", my_printf("\33b%s\33n %s", pak->from->resource, body+4));
- else
- DoMethod(data->msglist, CHATAREA_ADD, 0, pak->from->resource, body);
- }
- }
-
-
- void gchat_on(char *chan)
- {
- Object *win;
-
- win = NewObject(gui.gchat_mcc->mcc_Class, NULL, TAG_DONE);
- if(win)
- {
- DoMethod(gui.app, OM_ADDMEMBER, win);
- set(win, MUIA_Window_Open, TRUE);
- }
- }
-
-
- int gchat_packet(ikspak *pak)
- {
- struct gc_win *gcw;
- char *tmp;
-
- if(!gc_list) return(0);
-
- gcw = list_first(&gc_list);
- while(gcw)
- {
- if(iks_id_cmpx(pak->from, gcw->id, IKS_ID_USER | IKS_ID_SERVER) == 0)
- {
- DoMethod(gcw->win, GCHAT_PACKET, pak);
- return 1;
- }
- gcw = list_next(gcw);
- }
- return 0;
- }
-